/*
自定义 ENUM 类型 type XXX byte
const AAA XXX = '0'
*/
package zd

import (
	"context"
	"database/sql"
	"database/sql/driver"
	"reflect"
	"unsafe"

	"gitee.com/chunanyong/zorm"
)

// RegEnumByteType 自定义 byte 的 enum
func RegEnumByteType() {
	//RegisterCustomDriverValueConver 注册自定义的字段处理逻辑,用于驱动无法直接转换的场景,例如达梦的 TEXT 无法直接转化成 string
	//一般是放到init方法里进行注册
	zorm.RegisterCustomDriverValueConver("dm.CHAR", EnumType{})
	zorm.RegisterCustomDriverValueConver("postgresql.BPCHAR", EnumType{})
}

type EnumType struct{}

// GetDriverValue 根据数据库列类型,返回driver.Value的实例,struct属性类型
// 非struct类型接收,无法获取到structFieldType,会传入nil
func (e EnumType) GetDriverValue(ctx context.Context, columnType *sql.ColumnType, structFieldType *reflect.Type) (driver.Value, error) {
	return new(string), nil
}

// ConverDriverValue 数据库列类型,GetDriverValue返回的driver.Value的临时接收值,struct属性类型
// 非struct类型接收,无法获取到structFieldType,会传入nil
// 返回符合接收类型值的指针,指针,指针!!!!
func (e EnumType) ConverDriverValue(ctx context.Context, columnType *sql.ColumnType, tempDriverValue driver.Value, structFieldType *reflect.Type) (any, error) {
	val := tempDriverValue.(*string)
	if len(*val) == 1 {
		if structFieldType == nil { // map 方式时为 nil(因无法取到 structField)
			return val, nil // zorm.QueryMap 自定义 byte 取值为 "1"
		}
		if kind := (*structFieldType).Kind(); kind == reflect.Uint8 && (*structFieldType).Name() != "uint8" {
			// 变量类型为 structFieldType 否则提示类型不匹配
			c := byte((*val)[0])
			v := reflect.NewAt(*structFieldType, unsafe.Pointer(&c))
			return v.Interface(), nil
		}
	}
	return val, nil
}
